package org.com.gr.capserver.utils.hikvisionSDK;

import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import org.com.gr.capserver.utils.hikvisionSDK.sdk.HCNetSDK;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.ConcurrentHashMap;

import static org.com.gr.capserver.config.CommonConfig.hCNetSDK;

/**
 * ClassName: SDKBean
 * Description:
 *
 * @author binbin_hao
 * @date 2023/9/6 20:09
 */
@Component
@Slf4j
public class SDKBean {

   public static ConcurrentHashMap<String,Integer> lUserIDMap=new ConcurrentHashMap<>();

    public  String loginSDK(String ip,int port,String userName,String password,String serial){
        try {
            HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
            //登录设备，每一台设备只需要登录一次
            //int lUserID = this.login_V40("192.168.110.3", (short) 8000, "admin", "gr123456",m_strDeviceInfo);
            int lUserID = this.login_V40(ip, (short) port, userName, password,m_strDeviceInfo);
            if (lUserID>-1){
//                SM2 sm2 = SmUtil.sm2();
//                String key= sm2.encryptHex(String.valueOf(lUserID), KeyType.PublicKey);
                String sSerialNumber= new String(m_strDeviceInfo.struDeviceV30.sSerialNumber).trim();
                if (!StringUtils.isEmpty(serial)){
                    sSerialNumber=serial;
                }
                lUserIDMap.putIfAbsent(sSerialNumber,lUserID);
                System.out.println("模拟通道个数:"+ m_strDeviceInfo.struDeviceV30.byChanNum);
                System.out.println("通道起始通道号 :"+ m_strDeviceInfo.struDeviceV30.byStartChan);
                System.out.println("最大数字通道个数:"+ m_strDeviceInfo.struDeviceV30.byIPChanNum);
                System.out.println("设备序列号:"+new String(m_strDeviceInfo.struDeviceV30.sSerialNumber).trim());
                return sSerialNumber;
            }else {
                return "";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("登陆SDK异常，异常信息:{}",e.getMessage());
        }
        return "";
    }
    public boolean loginOutSDK(String key){
        try {
            if (lUserIDMap.containsKey(key)){
                int lUserId=lUserIDMap.get(key);
                lUserIDMap.remove(key);
                if(getDeviceStatus(lUserId)){
                    boolean isLogOut= hCNetSDK.NET_DVR_Logout(lUserId);
                    return isLogOut;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("退出登录SDK异常，异常信息:{}",e.getMessage());
        }
        return false;
    }
    public boolean controllerPanStart(String key,int command,int speed){
        try {
            if (lUserIDMap.containsKey(key)){
                int lUserId=lUserIDMap.get(key);
                if(getDeviceStatus(lUserId)){
                    boolean isControl=false;
                    if (speed>0){
                        isControl=  hCNetSDK.NET_DVR_PTZControlWithSpeed_Other(lUserId,1,command,0,speed);
                        Thread.sleep(100);
                        hCNetSDK.NET_DVR_PTZControlWithSpeed_Other(lUserId,1,command,1,speed);
                    }else {
                        isControl=  hCNetSDK.NET_DVR_PTZControl_Other(lUserId,1,command,0);
                        Thread.sleep(100);
                        isControl=  hCNetSDK.NET_DVR_PTZControl_Other(lUserId,1,command,1);
                    }
                   return isControl;
                }else {
                   lUserIDMap.remove(key);
                   return false;
               }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("云台控制开始，异常信息:{}",e.getMessage());
        }
        return false;
    }
    public boolean controllerPanEnd(String key,int command,int speed){
        try {
            log.info("设备登出");
            if (lUserIDMap.containsKey(key)){
                int lUserId=lUserIDMap.get(key);
                if(getDeviceStatus(lUserId)){
                    boolean isControl=false;
                    if (speed>0){
                        isControl=  hCNetSDK.NET_DVR_PTZControlWithSpeed_Other(lUserId,1,command,1,speed);
                    }else {
                        isControl=  hCNetSDK.NET_DVR_PTZControl_Other(lUserId,1,command,1);
                    }
                    return isControl;
                }else {
                    lUserIDMap.remove(key);
                    return false;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("云台控制结束，异常信息:{}",e.getMessage());
        }
        return false;
    }

//    public static void main(String[] args) throws IOException, InterruptedException {
//
//
//       /* HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
//        //登录设备，每一台设备只需要登录一次
//        lUserID = SDKBean.login_V40("192.168.110.3", (short) 8000, "admin", "gr123456",m_strDeviceInfo);
//        System.out.println("模拟通道个数:"+ m_strDeviceInfo.struDeviceV30.byChanNum);
//        System.out.println("通道起始通道号 :"+ m_strDeviceInfo.struDeviceV30.byStartChan);
//        System.out.println("最大数字通道个数:"+ m_strDeviceInfo.struDeviceV30.byIPChanNum);
//        System.out.println("设备序列号:"+new String(m_strDeviceInfo.struDeviceV30.sSerialNumber).trim());
//        boolean isControl=  hCNetSDK.NET_DVR_PTZControl_Other(lUserID,1,23,0);
//        Thread.sleep(100);
//        boolean isControl1=  hCNetSDK.NET_DVR_PTZControl_Other(lUserID,1,23,1);
//        System.out.println("is use2:"+isControl1);
//        Thread.sleep(10000);
//        if (hCNetSDK.NET_DVR_Logout(lUserID)) {
//            System.out.println("注销成功");
//        }
//
//        //释放SDK资源，程序退出时调用，只需要调用一次
//        hCNetSDK.NET_DVR_Cleanup();
//        return;*/
//    }
    int getChannelNumber(String sChannelName) {
        int iChannelNum = -1;
        if (sChannelName.charAt(0) == 'C')//Camara开头表示模拟通道
        {
            //子字符串中获取通道号
            iChannelNum = Integer.parseInt(sChannelName.substring(6));
        } else {
            if (sChannelName.charAt(0) == 'I')//IPCamara开头表示IP通道
            {
                //子字符创中获取通道号,IP通道号要加32
                //iChannelNum = Integer.parseInt(sChannelName.substring(8)) + m_strDeviceInfo.byStartDChan - 1;
                iChannelNum = Integer.parseInt(sChannelName.split("_")[1]);
            } else {
                return -1;
            }
        }
        return iChannelNum;
    }
    /**
     * 设备登录V30
     *
     * @param ip   设备IP
     * @param port SDK端口，默认设备的8000端口
     * @param user 设备用户名
     * @param psw  设备密码
     */
    private  int login_V30(String ip, short port, String user, String psw) {
        HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
        int iUserID = hCNetSDK.NET_DVR_Login_V30(ip, port, user, psw, m_strDeviceInfo);
        System.out.println("UserID:" + iUserID);
        if ((iUserID == -1) || (iUserID == 0xFFFFFFFF)) {
            System.out.println("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return iUserID;
        } else {
            System.out.println(ip + ":设备登录成功！");
            return iUserID;
        }
    }

    /**
     * 设备登录V40 与V30功能一致
     *
     * @param ip   设备IP
     * @param port SDK端口，默认设备的8000端口
     * @param user 设备用户名
     * @param psw  设备密码
     */
    private   int login_V40(String ip, short port, String user, String psw) {
        //注册
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息

        String m_sDeviceIP = ip;//设备ip地址
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());

        String m_sUsername = user;//设备用户名
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());

        String m_sPassword = psw;//设备密码
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());

        m_strLoginInfo.wPort = port;
        m_strLoginInfo.bUseAsynLogin = false; //是否异步登录：0- 否，1- 是
//        m_strLoginInfo.byLoginMode=1;  //ISAPI登录
        m_strLoginInfo.write();

        int iUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (iUserID == -1) {
            System.out.println("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return iUserID;
        } else {
            System.out.println(ip + ":设备登录成功！"+iUserID);
            return iUserID;
        }
    }
    private int login_V40(String ip, short port, String user, String psw,HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo) {
        //注册
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息

        String m_sDeviceIP = ip;//设备ip地址
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());

        String m_sUsername = user;//设备用户名
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());

        String m_sPassword = psw;//设备密码
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());

        m_strLoginInfo.wPort = port;
        m_strLoginInfo.bUseAsynLogin = false; //是否异步登录：0- 否，1- 是
//        m_strLoginInfo.byLoginMode=1;  //ISAPI登录
        m_strLoginInfo.write();

        int iUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (iUserID == -1) {
            System.out.println("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return iUserID;
        } else {
            System.out.println(ip + ":设备登录成功！"+iUserID);
            return iUserID;
        }
    }

    //设备在线状态监测
    private  boolean getDeviceStatus(int iUserID) {
        boolean devStatus = hCNetSDK.NET_DVR_RemoteControl(iUserID, HCNetSDK.NET_DVR_CHECK_USER_STATUS, null, 0);
        if (devStatus == false) {
            System.out.println("设备不在线");

        } else {
            System.out.println("设备在线");
        }
        return devStatus;
    }

    //PC电脑有多网卡，绑定网卡，指定使用的实际网卡
    private void getIP() {
        HCNetSDK.BYTE_TWODIM[] struByteArray = new HCNetSDK.BYTE_TWODIM[16];
        IntByReference pInt = new IntByReference(0);
        boolean pEnableBind = false;
        if (!hCNetSDK.NET_DVR_GetLocalIP(struByteArray, pInt, pEnableBind)) {
            System.out.println("NET_DVR_GetLocalIP失败，错误号:" + hCNetSDK.NET_DVR_GetLastError());
        } else {
            int inum = pInt.getValue();
            for (int i = 0; i < inum; i++) {
                System.out.println("网卡序号:" + i + ", 网卡IP: " + new String(struByteArray[i].strIP).trim());

//选择需要绑定的网卡
                if ("10.16.36.23".equals(new String(struByteArray[i].strIP))) {
                    hCNetSDK.NET_DVR_SetValidIP(i, true);
                }
            }
        }
    }



    //端口绑定
    private void bindPort() {
        HCNetSDK.NET_DVR_LOCAL_TCP_PORT_BIND_CFG strLocalTcpBind = new HCNetSDK.NET_DVR_LOCAL_TCP_PORT_BIND_CFG();
        strLocalTcpBind.read();
        strLocalTcpBind.wLocalBindTcpMinPort = 30000;
        strLocalTcpBind.wLocalBindTcpMaxPort = 30200;
        strLocalTcpBind.write();
        Pointer pStrLocalTcoBind = strLocalTcpBind.getPointer();
        if (hCNetSDK.NET_DVR_SetSDKLocalCfg(0, pStrLocalTcoBind) == false) {
            System.out.println("绑定失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
        }
        System.out.println("绑定成功");
    }




















}
